package com.openatc.agent.service;

import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.openatc.agent.utils.ApplicationContextProvider;
import com.openatc.agent.utils.RedisTemplateUtil;
import com.openatc.comm.data.MessageData;
import com.openatc.core.common.Constants;
import com.openatc.core.model.RESTRet;
import com.openatc.model.model.Channel;
import com.openatc.model.model.Phase;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author ：panleilei
 * @description 操作信号机特征参数
 * @modified By：
 * @version:
 * @date ：Created in 2023/4/14 13:41
 */
public abstract class FeatureRequest extends GenericMsgStrategy {
    @Override
    public RESTRet successSetProcess(MessageData requestData, RESTRet responseData) {
        String infotype = requestData.getInfotype();
        // 如果是特征参数的下载，向redis发布成功下载参数的消息
        if (infotype.contains("feature/")) {
            publishFeatureSetSuccessMsg(requestData);
        }
        return super.successSetProcess(requestData, responseData);
    }

    /**
     * 发布参数下载成功的消息
     * @param requestData
     */
    protected void publishFeatureSetSuccessMsg(MessageData requestData) {
        RedisTemplateUtil redisTemplateUtil = ApplicationContextProvider.getBean(RedisTemplateUtil.class);
        String channel = Constants.FEATURE_SET_CHANNEL + requestData.getInfotype() + ":" + requestData.getAgentid();
        String message = gson.toJson(requestData);
        redisTemplateUtil.publish(channel,message);
        redisTemplateUtil.setValue(channel,message);
    }
    /**
     * 检查是否需要填充通道类型/方向
     * @param channelList
     * @return
     */
    protected boolean checkFillChannelDirection(List<Channel> channelList) {
        if (channelList == null) return false;
        if (channelList.isEmpty()) return false;
        for (Channel channel : channelList) {
            // 通道没有类型，需要填充
            if (channel.getType() == null) return true;
            // 通道没有方向，需要填充
            if (CollectionUtils.isEmpty(channel.getRealdir())) return true;
        }
        return false;
    }

    /**
     * 填充通道中的方向
     *
     * @param channels
     * @param phases
     * @param overlaplList
     */
    protected void fillChannelDirection(JsonArray channels, List<Phase> phases, JsonArray overlaplList) {
        if (CollectionUtils.isEmpty(phases)) {
            logger.warning("Fill channel direction failed! Phases is null!");
            return;
        }
        if (channels.isEmpty()) {
            logger.warning("Fill channel direction failed! Channel is null!");
            return;
        }
        Map<Integer, Phase> phaseMap = phases.stream().collect(Collectors.toMap(Phase::getId, Function.identity()));
        Map<Integer, JsonObject> overLapls = overlaplList.asList().stream().map(JsonElement::getAsJsonObject)
                .collect(Collectors.toMap(jsonObject -> jsonObject.get("id").getAsInt(), Function.identity()));
        for (JsonElement channel : channels) {
            JsonObject channelObj = channel.getAsJsonObject();
            JsonArray realdir = channelObj.get("realdir").getAsJsonArray();
            boolean haseType = channelObj.has("type");
            // 通道的方向为空时，填充
            if (realdir.size() == 0) {
                int controlType = channelObj.get("controltype").getAsInt();
                int controlSource = channelObj.get("controlsource").getAsInt();
                // 机动车相位--2
                if (controlType == 2) {
                    Phase phase = phaseMap.get(controlSource);
                    List<Integer> direction = phase.getDirection();
                    if (direction.size() != 1) continue;
                    realdir.add(direction.get(0));
                    if (!haseType) {
                        channelObj.addProperty("type",0);
                    }
                }
                // 行人相位--3
                else if (controlType == 3) {
                    Phase phase = phaseMap.get(controlSource);
                    List<Integer> peddirection = phase.getPeddirection();
                    if (peddirection.size() != 1) continue;
                    realdir.add(peddirection.get(0));
                    if (!haseType) {
                        channelObj.addProperty("type",2);
                    }
                }
                // 跟随相位--4
                else if (controlType == 4) {
                    JsonObject overLapObj = overLapls.get(controlSource);
                    JsonArray direction = overLapObj.get("direction").getAsJsonArray();
                    if (direction.size() != 1) continue;
                    realdir.add(direction.get(0).getAsInt());
                    if (!haseType) {
                        channelObj.addProperty("type",0);
                    }
                }
                // 行人跟随相位--5
                else if (controlType == 5) {
                    JsonObject overLapObj = overLapls.get(controlSource);
                    JsonArray direction = overLapObj.get("peddirection").getAsJsonArray();
                    if (direction.size() != 1) continue;
                    realdir.add(direction.get(0).getAsInt());
                    if (!haseType) {
                        channelObj.addProperty("type",2);
                    }
                }
            }
        }
    }

}
